const BASE_UNIT = 100

export function mapCompositionCoord(composition) {
  const converts = {
    SINGLE: calcSingle,
    LEFT_RIGHT: calcLeftRight,
    LEFT_CENTER_RIGHT: calcLeftCenterRight,
    TOP_BOTTOM: calcTopBottom,
    TOP_MIDDLE_BOTTOM: calcTopMiddleBottom,
  }
  const convert = converts[composition.structure]
  const coordinate = convert && convert(composition);
  return coordinate;
}

export function mapCompositionCoordArr(composition) {
  const coordinate = mapCompositionCoord(composition)
  const _objToArrMode = (compCoord) => {
    let coordArr = []
    for (let key in compCoord) {
      coordArr.push(compCoord[key])
    }
    return coordArr
  }
  return _objToArrMode(coordinate)
}

function scaleWidth(part = {}, partRatio = 1) {
  const ratio = part.based !== 'height' ? 1 : partRatio
  const width = BASE_UNIT * part.size * ratio
  return width
}

const calcSingle = (composition) => {
  const { SINGLE } = composition.components
  const { width, height } = _extractViewBox(SINGLE.svgCode)
  return { SINGLE: { x: 0, y: 0, width, height, graphicId: SINGLE.graphicId } }
}

const calcLeftRight = (composition) => {
  const { components: { LEFT, RIGHT }, align } = composition;

  const leftMargin = extractMargin(LEFT.margin)
  const leftRatio = getAspectRatio(LEFT.svgCode)
  const rightMargin = extractMargin(RIGHT.margin)
  const rightRatio = getAspectRatio(RIGHT.svgCode)

  let leftSvg = { x: leftMargin.left, graphicId: LEFT.graphicId }
  leftSvg.width = scaleWidth(LEFT, leftRatio)
  leftSvg.height = leftSvg.width / leftRatio

  let rightSvg = { x: leftSvg.x + leftSvg.width + leftMargin.right + rightMargin.left, graphicId: RIGHT.graphicId }
  rightSvg.width = scaleWidth(RIGHT, rightRatio)
  rightSvg.height = rightSvg.width / rightRatio

  const maxKey = _findMaxValueKey({ left: leftSvg, right: rightSvg }, 'height')
  if (maxKey === 'left') {
    if (align === 'top') {
      leftSvg.y = leftMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'middle') {
      leftSvg.y = leftMargin.top
      rightSvg.y = (leftSvg.height - rightSvg.height) / 2 + rightMargin.top
    }
    if (align === 'bottom') {
      leftSvg.y = leftMargin.top
      rightSvg.y = leftSvg.height - rightSvg.height + rightMargin.top
    }
  }
  if (maxKey === 'right') {
    if (align === 'top') {
      leftSvg.y = leftMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'middle') {
      leftSvg.y = (rightSvg.height - leftSvg.height) / 2 + leftMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'bottom') {
      leftSvg.y = rightSvg.height - leftSvg.height + leftMargin.top
      rightSvg.y = rightMargin.top
    }
  }

  return { LEFT: addDirection(leftSvg), RIGHT: addDirection(rightSvg) }
}

const calcLeftCenterRight = (composition) => {
  const { components: { LEFT, CENTER, RIGHT }, align } = composition;

  const leftMargin = extractMargin(LEFT.margin)
  const leftRatio = getAspectRatio(LEFT.svgCode)
  const centerMargin = extractMargin(CENTER.margin)
  const centerRatio = getAspectRatio(CENTER.svgCode)
  const rightMargin = extractMargin(RIGHT.margin)
  const rightRatio = getAspectRatio(RIGHT.svgCode)

  let leftSvg = { x: leftMargin.left, graphicId: LEFT.graphicId }
  let centerSvg = { x: 0, graphicId: CENTER.graphicId }
  let rightSvg = { x: 0, graphicId: RIGHT.graphicId }
  leftSvg.width = scaleWidth(LEFT, leftRatio)
  leftSvg.height = leftSvg.width / leftRatio
  centerSvg.x = leftSvg.x + leftSvg.width + leftMargin.right + centerMargin.left
  centerSvg.width = scaleWidth(CENTER, centerRatio)
  centerSvg.height = centerSvg.width / centerRatio
  rightSvg.x = centerSvg.x + centerSvg.width + centerMargin.right + rightMargin.left
  rightSvg.width = scaleWidth(RIGHT, rightRatio)
  rightSvg.height = rightSvg.width / rightRatio

  const maxKey = _findMaxValueKey({ left: leftSvg, center: centerSvg, right: rightSvg }, 'height')

  if (maxKey === 'left') {
    if (align === 'top') {
      leftSvg.y = leftMargin.top
      centerSvg.y = centerMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'middle') {
      leftSvg.y = leftMargin.top
      centerSvg.y = (leftSvg.height - centerSvg.height) / 2 + centerMargin.top
      rightSvg.y = (leftSvg.height - rightSvg.height) / 2 + rightMargin.top
    }
    if (align === 'bottom') {
      leftSvg.y = leftMargin.top
      centerSvg.y = leftSvg.height - centerSvg.height + centerMargin.top
      rightSvg.y = leftSvg.height - rightSvg.height + rightMargin.top
    }
  }

  if (maxKey === 'center') {
    if (align === 'top') {
      leftSvg.y = leftMargin.top
      centerSvg.y = centerMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'middle') {
      leftSvg.y = (centerSvg.height - leftSvg.height) / 2 + leftMargin.top
      centerSvg.y = centerMargin.top
      rightSvg.y = (centerSvg.height - rightSvg.height) / 2 + rightMargin.top
    }
    if (align === 'bottom') {
      leftSvg.y = centerSvg.height - leftSvg.height + leftMargin.top
      centerSvg.y = centerMargin.top
      rightSvg.y = centerSvg.height - rightSvg.height + rightMargin.top
    }
  }

  if (maxKey === 'right') {
    if (align === 'top') {
      leftSvg.y = leftMargin.top
      centerSvg.y = centerMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'middle') {
      leftSvg.y = (rightSvg.height - leftSvg.height) / 2 + leftMargin.top
      centerSvg.y = (rightSvg.height - centerSvg.height) / 2 + centerMargin.top
      rightSvg.y = rightMargin.top
    }
    if (align === 'bottom') {
      leftSvg.y = rightSvg.height - leftSvg.height + leftMargin.top
      centerSvg.y = rightSvg.height - centerSvg.height + centerMargin.top
      rightSvg.y = rightMargin.top
    }
  }

  return { LEFT: addDirection(leftSvg), CENTER: addDirection(centerSvg), RIGHT: addDirection(rightSvg) }
}

const calcTopBottom = (composition) => {
  const { components: { TOP, BOTTOM }, align } = composition;

  const topMargin = extractMargin(TOP.margin)
  const topRatio = getAspectRatio(TOP.svgCode)
  const bottomMargin = extractMargin(BOTTOM.margin)
  const bottomRatio = getAspectRatio(BOTTOM.svgCode)

  let topSvg = { y: topMargin.top, graphicId: TOP.graphicId }
  topSvg.width = scaleWidth(TOP, topRatio)
  topSvg.height = topSvg.width / topRatio

  let bottomSvg = { y: topSvg.y + topSvg.height + topMargin.bottom + bottomMargin.top, graphicId: BOTTOM.graphicId }
  bottomSvg.width = scaleWidth(BOTTOM, bottomRatio)
  bottomSvg.height = bottomSvg.width / bottomRatio

  const maxKey = _findMaxValueKey({ top: topSvg, bottom: bottomSvg }, 'width')
  if (maxKey === 'top') {
    if (align === 'left') {
      topSvg.x = topMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'center') {
      topSvg.x = topMargin.left
      bottomSvg.x = (topSvg.width - bottomSvg.width) / 2 + bottomMargin.left
    }
    if (align === 'right') {
      topSvg.x = topMargin.left
      bottomSvg.x = topSvg.width - bottomSvg.width + bottomMargin.left
    }
  }
  if (maxKey === 'bottom') {
    if (align === 'left') {
      topSvg.x = topMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'center') {
      topSvg.x = (bottomSvg.width - topSvg.width) / 2 + topMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'right') {
      topSvg.x = bottomSvg.width - topSvg.width + topMargin.left
      bottomSvg.x = bottomMargin.left
    }
  }

  return { TOP: addDirection(topSvg), BOTTOM: addDirection(bottomSvg) }
}

const calcTopMiddleBottom = (composition) => {
  const { components: { TOP, MIDDLE, BOTTOM }, align } = composition;

  const topMargin = extractMargin(TOP.margin)
  const topRatio = getAspectRatio(TOP.svgCode)
  const middleMargin = extractMargin(MIDDLE.margin)
  const middleRatio = getAspectRatio(MIDDLE.svgCode)
  const bottomMargin = extractMargin(BOTTOM.margin)
  const bottomRatio = getAspectRatio(BOTTOM.svgCode)

  let topSvg = { y: topMargin.top, graphicId: TOP.graphicId }
  topSvg.width = scaleWidth(TOP, topRatio)
  topSvg.height = topSvg.width / topRatio

  let middleSvg = { y: topSvg.y + topSvg.height + topMargin.bottom + bottomMargin.top, graphicId: MIDDLE.graphicId }
  middleSvg.width = scaleWidth(MIDDLE, middleRatio)
  middleSvg.height = middleSvg.width / middleRatio

  let bottomSvg = { y: middleSvg.y + middleSvg.height + middleMargin.bottom + bottomMargin.top, graphicId: BOTTOM.graphicId }
  bottomSvg.width = scaleWidth(BOTTOM, bottomRatio)
  bottomSvg.height = bottomSvg.width / bottomRatio

  const maxKey = _findMaxValueKey({ top: topSvg, middle: middleSvg, bottom: bottomSvg }, 'width')
  if (maxKey === 'top') {
    if (align === 'left') {
      topSvg.x = topMargin.left
      middleSvg.x = middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'center') {
      topSvg.x = topMargin.left
      middleSvg.x = (topSvg.width - middleSvg.width) / 2 + middleMargin.left
      bottomSvg.x = (topSvg.width - bottomSvg.width) / 2 + bottomMargin.left
    }
    if (align === 'right') {
      topSvg.x = topMargin.left
      middleSvg.x = topSvg.width - middleSvg.width + middleMargin.left
      bottomSvg.x = topSvg.width - bottomSvg.width + bottomMargin.left
    }
  }
  if (maxKey === 'middle') {
    if (align === 'left') {
      topSvg.x = topMargin.left
      middleSvg.x = middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'center') {
      topSvg.x = (bottomSvg.width - topSvg.width) / 2 + topMargin.left
      middleSvg.x = (bottomSvg.width - middleSvg.width) / 2 + middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'right') {
      topSvg.x = bottomSvg.width - topSvg.width + topMargin.left
      middleSvg.x = bottomSvg.width - middleSvg.width + middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
  }
  if (maxKey === 'bottom') {
    if (align === 'left') {
      topSvg.x = topMargin.left
      middleSvg.x = middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'center') {
      topSvg.x = (bottomSvg.width - topSvg.width) / 2 + topMargin.left
      middleSvg.x = (bottomSvg.width - middleSvg.width) / 2 + middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
    if (align === 'right') {
      topSvg.x = bottomSvg.width - topSvg.width + topMargin.left
      middleSvg.x = bottomSvg.width - middleSvg.width + middleMargin.left
      bottomSvg.x = bottomMargin.left
    }
  }

  return { TOP: addDirection(topSvg), MIDDLE: addDirection(middleSvg), BOTTOM: addDirection(bottomSvg) }
}

function _extractViewBox(svgCode = '') {
  const viewBoxRegex = /viewBox="([^"]+)"/;
  const match = svgCode.match(viewBoxRegex);
  if (!match) { return {}; }
  let viewBox = match[1].split(' ')
  viewBox = viewBox.map(item => parseFloat(item));
  return { width: viewBox[2], height: viewBox[3] };
}

function extractMargin(margin = '0 0 0 0') {
  let marginArr = margin.split(' ')
  if (marginArr.length !== 4) { marginArr = [0, 0, 0, 0] }
  const margins = marginArr.map(item => parseFloat(item) * BASE_UNIT);
  return { top: margins[0], right: margins[1], bottom: margins[2], left: margins[3], }
}

function getAspectRatio(svgCode) {
  if (!svgCode) { return 1 }
  const viewBox = _extractViewBox(svgCode)
  return viewBox.width / viewBox.height
}


function _findMaxValueKey(obj, subkey = 'height') {
  let maxValue = -Infinity
  let maxKey = ''
  Object.keys(obj).forEach(key => {
    if (obj[key][subkey] > maxValue) {
      maxValue = obj[key][subkey];
      maxKey = key
    }
  });
  return maxKey
}

function addDirection(elem) {
  return elem
  elem.left = elem.x
  elem.top = elem.y
  elem.unit = 'px'
  return elem
}


const mockComposition = {
  "id": 2,
  "brandId": 2,
  "name": "Yi_Normal",
  "thumbnail": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 470 100\"><symbol id=\"graphic-2\" viewBox=\"0 0 300 200\"><ellipse cx=\"150\" cy=\"100\" rx=\"150\" ry=\"100\"/></symbol><symbol id=\"graphic-3\" viewBox=\"0 0 290 100\"><rect width=\"290\" height=\"100\" rx=\"20\"/></symbol><use xlink:href=\"#graphic-2\" x=\"0\" y=\"0\" width=\"150\" height=\"100\" /><use xlink:href=\"#graphic-3\" x=\"180\" y=\"0\" width=\"290\" height=\"100\" /></svg>",
  "safePadding": "0.00",
  "minimumWidth": [],
  "structure": "LEFT_RIGHT",
  "align": "middle",
  "components": {
    "LEFT": {
      "graphicId": 2,
      "based": "height",
      "size": 1,
      "margin": "0 0.3 0 0",
      "name": "YiQi_logo",
      "svgCode": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 300 200\"><ellipse cx=\"150\" cy=\"100\" rx=\"150\" ry=\"100\"/></svg>"
    },
    "RIGHT": {
      "graphicId": 3,
      "based": "height",
      "size": 1,
      "margin": "0 0 0 0",
      "name": "YiQi_type",
      "svgCode": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 290 100\"><rect width=\"290\" height=\"100\" rx=\"20\"/></svg>"
    }
  },
  "isPrivate": false
}
